home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 316 / libsrc / crt0.s < prev    next >
Encoding:
Text File  |  1988-10-20  |  6.3 KB  |  228 lines

  1. |
  2. |        Cross Development System for Atari ST 
  3. |      Copyright (c) 1988, Memorial University of Newfoundland
  4. |
  5. |  C start-up routine.  Has several tasks to do:
  6. |    release unneeded memory to the system
  7. |    set up stack
  8. |    set up argc, argv, and envp
  9. |    set up an address trap handler for bsr.l instructions
  10. |  Also defines _exit() so the address error handler can be restored
  11. |
  12. | $Header: crt0.s,v 1.3 88/02/03 20:23:26 m68k Exp $
  13. |
  14. | $Log:    crt0.s,v $
  15. | Revision 1.3  88/02/03  20:23:26  m68k
  16. | Added __in_trap flag - see atari/alarm()
  17. | Revision 1.2  88/01/29  17:24:37  m68k
  18. | Re-wrote the argument parsing stuff
  19. | Calls exit() instead of _exit()
  20. | uses Setvec() trap instead of Super()/mov/Super() to change the ae trap
  21. | stack now has initial size of 8k (up from 2)
  22. |
  23.     .globl    __start
  24.     .globl    __exit
  25.     .globl    __base
  26.     .globl    _environ
  27.     .globl    _main
  28.     .globl    _errno
  29.     .globl    __in_trap
  30.  
  31.     .comm    __base,4
  32.     .comm    __stksize,4
  33.     .comm    _environ,4
  34.     .comm    _errno,4
  35.     .comm    old_aet,4
  36.     .comm    __in_trap,1
  37.  
  38.     .text
  39.  
  40. __start:
  41.     movl    a7@(4), a5
  42.     movl    a5, __base
  43.  
  44.     | set up envp[] and argv[] stuff
  45.     movl    a5@(0x18), a1        | envp = basepage->bss_address
  46.     addl    a5@(0x1c), a1        |    + basepage->bss_size;
  47.     movl    a1, _environ        | _environ = envp;
  48.     movl    a5@(0x2c), a2        | ep = basepage->envp;
  49. L0:    tstb    a2@            | while (*ep) {
  50.     beq    L3            |
  51.     movl    a2, a1@+        |    *envp++ = ep;
  52. L2:    tstb    a2@+            |    while (*ep++)
  53.     bne    L2            |        ;
  54.     bra    L0            | }
  55. L3:    clrl    a1@+            | *envp++ = (char *) 0; 
  56.     |  From here down to 0: is only relivent if you are using the mark
  57.     | williams shell, which passes the arguments in the environment as
  58.     | well as the base page (also passes argv[0]).  The start of the
  59.     | arguments is marked by a env variable by the name ARGV (which has
  60.     | some i/o vector stuff in it - not used).
  61.     movl    _environ, a3        |
  62. L1:    tstl    a3@            | for (s = environ ; *s ; s++)
  63.     beq    L7            |
  64.     movl    a3@+, a4        |    if (strncmp(*s, "ARGV=", 5))
  65.     cmpb    #0x41, a4@+        |
  66.     bne    L1            |
  67.     cmpb    #0x52, a4@+        |
  68.     bne    L1            |
  69.     cmpb    #0x47, a4@+        |
  70.     bne    L1            |
  71.     cmpb    #0x56, a4@+        |
  72.     bne    L1            |
  73.     cmpb    #0x3d, a4@+        |
  74.     bne    L1            |    {
  75.     clrl    a3@-            |        *--s = 0;
  76.     movl    a3, a2            |        argv = s + 2;
  77.     addql    #0x4, a2        |
  78.     movl    a1, a0            |        
  79.     movl    a1, d3            |        argc = (&a1[1] - argv)
  80.     subl    a2, d3            |            / sizeof(long);    
  81.     subql    #0x4, d3        |
  82.     asrl    #0x2, d3        |        break;
  83.     bra    L6            |    }
  84. L7:                    | /* a1: envp -> argbuf */
  85.     movl    a1, a0            | argv = argbuf
  86.     addl    #128, a0        |     + sizeof(baseage->cmdline);
  87.     clrw    a0@+            | *((short)argv)++ = 0;
  88.     movl    a1, d1            | argstart = argbuf;
  89.     movl    a0, a2            | saveargv = argv;
  90. |    movew    #1, d3            | argc = 1;
  91.     movel    #1, d3            | .. jrd
  92.     movl    #arg0, a0@+        | *argv++ = "arg0.prg";
  93.     movl    #0x80, a3        | cmdline = basepage->cmdline;
  94.     addl    a5, a3            |
  95.     moveb    a3@, d0            | /* # of chars in cmdline buf (128) */
  96. L8:    subqb    #1, d0            | while (d0-- > 0)
  97. |    ble    L9            |
  98.     blt    L9            | .. jrd
  99.     addql    #1, a3            |     if (*++cmdline == 0)
  100.     tstb    a3@            |     {
  101.     bne    L11            |
  102. L9:    cmpl    a1, d1            |        if (argbuf != argstart)
  103.     beq    L10            |        {
  104.     clrb    a1@+            |            *argbuf++ = '\0';
  105.     movl    d1, a0@+        |            *argv++ = argstart;
  106. |    addqw    #1, d3            |            argc++;
  107.     addql    #1, d3
  108.                     |        }
  109. L10:    clrl    a0@+            |        *argv++ = (char *) NULL;
  110.     bra    L6            |         break;
  111. L11:    cmpb    #0x20, a3@        |     } else if (*cmdline == ' ')
  112.     bne    L12            |     {
  113. |    addqw    #1, d3            |        argc++;
  114.     addql    #1,d3            | .. jrd
  115.     movl    d1, a0@+        |        *argv++ = argstart;
  116.     clrb    a1@+            |        *argbuf++ = '\0';
  117.     movl    a1, d1            |        argstart = argbuf;
  118.     bra    L8            |     } else
  119. L12:    moveb    a3@, a1@+        |        *argbuf++ = *cmdline;
  120.     bra    L8
  121.  
  122. L6:
  123.     movl    a0, a3            | reserve = argv - __base;
  124.     subl    a5, a3
  125.     tstl    __stksize        | if (!__stksize)
  126.     bne    L13            |
  127.     movl    #0x2000, __stksize    |    __stksize = 8 * 1024;
  128. L13:    addl    __stksize, a3        | reserve += __stksize;
  129.     movl    a3, d1
  130.     addl    a5, d1            | compute stack top
  131.     andl    #-2, d1            | even boundry
  132.     movl    d1, sp            | set up user stack
  133.  
  134.     movl    a3, sp@-
  135.     movl    a5, sp@-
  136.     clrw    sp@-
  137.     movw    #0x4a, sp@-
  138.     bset    #0, __in_trap
  139.     trap    #1            | release excess storage
  140.     bclr    #0, __in_trap
  141.     addl    #12, sp
  142.  
  143.     movl    _environ, sp@-        | push saveenvp
  144.     movl    a2, sp@-        | push saveargv
  145. |    movw    d3, sp@-        | push argc
  146.     movel    d3,sp@-            | .. jrd
  147.  
  148.     subl    a6, a6            | clear link reg - why I don't know
  149.  
  150.     | here we set up a trap handler for address errors - this is used in
  151.     | doing long branches and long bsrs (see comments in Leat()).
  152.  
  153.     movl    #aet, sp@-    | set address error vector to our handler
  154.     movew    #0xc, sp@-
  155.     movew    #0x5, sp@-
  156.     bset    #0, __in_trap
  157.     trap    #13
  158.     bclr    #0, __in_trap
  159.     addql    #0x8, sp
  160.     movl    d0, old_aet    | save old trap handler
  161.  
  162. |    jsr    _main
  163.     jsr    __main        | -- jrd.  call the standard wrapper fun
  164.     movew    d0, sp@-
  165.     jsr    _exit        | _exit calls __exit
  166.     | Not reached
  167.  
  168. |
  169. | _exit is here because it has to restore the old address error vector
  170. |
  171. __exit:
  172.     movl    old_aet, sp@-    | restore old address trap before we exit
  173.     movew    #0xc, sp@-
  174.     movew    #0x5, sp@-
  175.     bset    #0, __in_trap
  176.     trap    #13
  177.     bclr    #0, __in_trap
  178.     addql    #0x8, sp
  179. |    movew    sp@(0x4), sp@-    | .. jrd
  180.     movel    sp@(4),d0
  181.     movew    d0,sp@-
  182.     movew    #0x4c, sp@-
  183.     bset    #0, __in_trap
  184.     trap    #1
  185.     | The End.
  186.  
  187. |  This is a trap handler for address errors.  It is used in doing long
  188. | branches and long bsrs.  It looks to see if a long branch (0x6?ff) caused
  189. | the trap and if the destination is valid (not an odd address).  If so
  190. | the branch is taken and we return, otherwise, we call the old address
  191. | trapper.
  192. aet:
  193.     | d0, and a1 used 0x8080/101
  194.     | exp_frame is distance from top of stack to exception frame
  195.     Lexp_frame = 8            | 2 * sizeof(register)
  196.     moveml    #0x8080, sp@-        | save registers used
  197.     movw    sp@(Lexp_frame+6), d0    | the bad instruction
  198.     andw    #0xf0ff, d0
  199.     cmpw    #0x60ff, d0        | is a b?? instruction?
  200.     jne    L20            | nop, call old ae trap
  201.  
  202.     movl    sp@(Lexp_frame+10), a0    | the pc (currently bewtixt branch)
  203.     addql    #1, a0            | increment to long offset
  204.     addl    a0@, a0            | calculate new pc
  205.     movl    a0, d0
  206.     andb    #1, d0            | are we still an odd address?
  207.     jne    L20            | yep, get out.
  208.  
  209.     movl    a0, sp@(Lexp_frame+10)    | put new pc into the stack frame
  210.     cmpw    #0x61ff, sp@(Lexp_frame+6)    | if this is a bsrl
  211.     jne    L21            |  we need to fix up the return
  212.     movl    usp, a0            |  address on the user stack
  213.     addql    #4, a0@
  214. L21:
  215.     moveml    sp@+, #0x0101        | restore regs
  216.     addql    #8,sp            | pop part of stack frame
  217.     rte
  218.  
  219. L20:
  220.     moveml    sp@+, #0x0101
  221.     movl    old_aet, sp@(-4)    | done this way so no regs get mussed up
  222.     jmp    sp@(-4)
  223.  
  224. .data
  225. arg0:    .ascii "arg0\0"
  226.